#include "MainWindow.h"
#include "ui_MainWindow.h"
#include <QFileDialog>
#include <QResizeEvent>
#include <SelectPassDialog.h>
#include <NoteAddDialog.h>
#include <CryptoAgent.h>
#include <QMessageBox>
#include <QFontDatabase>
#include <SendMailDialog.h>
#include <QGridLayout>
#include <QtWebKit/QWebView>
#include <INoteView.h>

MainWindow::MainWindow(QWidget *parent) :
	QMainWindow(parent),
	ui(new Ui::MainWindow)
{
	ui->setupUi(this);
	connect(ui->settingsWidget,SIGNAL(hidePanel()),SLOT(onBtnHidePanel()));
	connect(ui->btnShowPanel,SIGNAL(clicked()),SLOT(onBtnShowPanel()));

	_views.append(ui->comboTab);
	_views.append(ui->listTab);
	_views.append(ui->tableTab);
	ui->tabWidget->setCurrentIndex(0);

	ui->tabWidget->setStyleSheet("QTabBar::tab { height: 0px; } "
								 "QTabBar::tab:selected { background: lightgray; }"
								 "QTabWidget::pane { border: 0; } ");

	_provider = new DataProvider(new DataBaseAgent(), this);
	_provider->setStatusBar(ui->statusBar);
	_provider->getDatabase()->setCryptoAgent(_provider->getCrypt());

	readSettings();

	ui->settingsWidget->setDataProvider(_provider);

	_expanded = _provider->settings()->expanded;

	ui->comboTab->setProvider(_provider);
	ui->listTab->setProvider(_provider);
	ui->tableTab->setProvider(_provider);

	_timer = new QTimer(this);
	_timer->singleShot(1000,this,SLOT(onTimerSignal()));

	// VIEW BINDING
	connect(ui->comboTab,SIGNAL(onBtnAddNote()),SLOT(onBtnAddNote()));
	connect(ui->comboTab,SIGNAL(onBtnEditNote(Note*)),SLOT(onBtnEditNote(Note*)));
	connect(_provider,SIGNAL(noteAdded(Note*)),ui->comboTab,SLOT(onNoteAdded(Note*)));
	connect(_provider,SIGNAL(noteRemoved(Note*)),ui->comboTab,SLOT(onNoteRemoved(Note*)));
	connect(_provider,SIGNAL(noteUpdated(Note*)),ui->comboTab,SLOT(onNoteUpdated(Note*)));

	connect(ui->listTab,SIGNAL(onBtnAddNote()),SLOT(onBtnAddNote()));
	connect(ui->listTab,SIGNAL(onBtnEditNote(Note*)),SLOT(onBtnEditNote(Note*)));
	connect(_provider,SIGNAL(noteAdded(Note*)),ui->listTab,SLOT(onNoteAdded(Note*)));
	connect(_provider,SIGNAL(noteRemoved(Note*)),ui->listTab,SLOT(onNoteRemoved(Note*)));
	connect(_provider,SIGNAL(noteUpdated(Note*)),ui->listTab,SLOT(onNoteUpdated(Note*)));

	connect(ui->tableTab,SIGNAL(onBtnAddNote()),SLOT(onBtnAddNote()));
	connect(ui->tableTab,SIGNAL(onBtnEditNote(Note*)),SLOT(onBtnEditNote(Note*)));
	connect(_provider,SIGNAL(noteAdded(Note*)),ui->tableTab,SLOT(onNoteAdded(Note*)));
	connect(_provider,SIGNAL(noteRemoved(Note*)),ui->tableTab,SLOT(onNoteRemoved(Note*)));
	connect(_provider,SIGNAL(noteUpdated(Note*)),ui->tableTab,SLOT(onNoteUpdated(Note*)));

	// MENU BINDING
	connect(_provider,SIGNAL(DBStateChanged()),SLOT(onDBStateChanged()));

	connect(ui->menuWindow_style,SIGNAL(triggered(QAction*)),SLOT(onWindowStyleChanged(QAction*)));
	connect(ui->menuTable_style,SIGNAL(triggered(QAction*)),SLOT(onTableStyleChanged(QAction*)));

	connect(ui->actionAbout,SIGNAL(triggered()),SLOT(onAbout()));
	connect(ui->actionContact_author,SIGNAL(triggered()),SLOT(onSendMail()));
	connect(ui->actionHelp,SIGNAL(triggered()),SLOT(onHelp()));
	connect(ui->actionSelectDB,SIGNAL(triggered()),ui->settingsWidget,SLOT(onBtnDBLocation()));
	connect(ui->actionChangePass,SIGNAL(triggered()),ui->settingsWidget,SLOT(onBtnChangePass()));
	connect(ui->actionMakeBackup,SIGNAL(triggered()),SLOT(onMakeBackup()));
	connect(ui->actionExit,SIGNAL(triggered()),SLOT(close()));

	// INIT
	onWindowStyleChanged(ui->menuWindow_style->actions().at(_provider->settings()->windowStyle));
	onTableStyleChanged(ui->menuTable_style->actions().at(_provider->settings()->dataViewStyle));

	if(!_provider->getDatabase()->setDataBase(_provider->settings()->database) ){
		ui->statusBar->showMessage(tr("Database connect error!"), 3000);
	}

	ui->btnShowPanel->setStyleSheet(INoteView::getButtonStyle("show"));

	onDBStateChanged();
}

MainWindow::~MainWindow()
{
	_provider->getDatabase()->close();
	delete ui;
}

void MainWindow::onDBStateChanged()
{
	if(!_provider) return;
	bool state = _provider->isDBLoaded();
	ui->actionChangePass->setEnabled(state);
	ui->actionMakeBackup->setEnabled(state);
}

void MainWindow::onTimerSignal()
{
	if(!_provider->settings()->showDlgAtStartup) return;
	SelectPassDialog dlg(_provider,this);
	dlg.exec();
	//if(dlg.exec() == QDialog::Accepted){
		_provider->getCrypt()->setPassword(dlg.getCipherType(), dlg.getPass());
		ui->settingsWidget->updatePass(dlg.getCipherType(), dlg.getPass());
	//}

	if(!_provider->getDatabase()->setDataBase(_provider->settings()->database) ){
		ui->statusBar->showMessage(tr("Database connect error!"), 3000);
	}
	else{
		_provider->loadDatabase();
	}
}

void MainWindow::onAbout()
{
	QMessageBox::information(this,tr("About"),QString("<p align='center'>Memorizer v. %1<br>Release date: %2  %3</p>"
											   "<p align='right'><i>Made by Eugene</i></p>").arg(QApplication::applicationVersion()).arg(BUILDDATE).arg(BUILDTIME),0);
}

void MainWindow::onSendMail()
{
	SendMailDialog dlg;
	dlg.exec();
}

void MainWindow::onBtnAddNote()
{
	if(!_provider->isDBLoaded()){
		QMessageBox::warning(this,tr("Database not loaded"),tr("Load database first."));
		return;
	}
	NoteAddDialog dlg;
	dlg.exec();

	Note* note = dlg.getNote();
	if(note == NULL) return;

	_provider->addNote(note);
}

void MainWindow::onBtnEditNote(Note* note)
{
	NoteAddDialog dlg(note);
	dlg.exec();

	_provider->updateNote(note);
}

void MainWindow::resizeEvent(QResizeEvent* event)
{
	int dx = _expanded ? 180 : 0;
	QRect menu(0,0,width(),24);
	QRect settings(-180+dx,9+24,180,height()-33-25);
	QRect view(dx,9+24,width()-dx,height()-33-25);
	QRect show(0,height()-33+9-33,20,33);

	ui->menuBar->setGeometry(menu);
	ui->settingsWidget->setGeometry(settings);
	ui->tabWidget->setGeometry(view);
	ui->btnShowPanel->setGeometry(show);

	ui->btnShowPanel->setVisible(!_expanded);
}

void MainWindow::setCurrentView(INoteView* view)
{
	foreach(INoteView* vw, _views){
		vw->setVisible( vw == view );
	}
	_currentView = view;
}

void MainWindow::onBtnHidePanel()
{
	animateWindow(true);
}

void MainWindow::onBtnShowPanel()
{
	animateWindow(false);
	ui->btnShowPanel->setVisible(false);
}

void MainWindow::animateWindow(bool hide)
{
	_expanded = !hide;
	QWidget* slide = ui->tabWidget;
	int dx = ui->settingsWidget->width();
	QPoint point1(-dx, ui->settingsWidget->pos().y());
	QPoint point2(0, ui->settingsWidget->pos().y());
	QRect rect1(0, slide->pos().y(), slide->width() + dx, slide->height());
	QRect rect2(dx, slide->pos().y(), slide->width() - dx, slide->height());

	// then a animation:
	QPropertyAnimation *animation = new QPropertyAnimation(ui->settingsWidget, "pos");
	animation->setDuration(1000);
	animation->setEasingCurve(QEasingCurve::InOutCubic); //InOutBack
	animation->setStartValue(ui->settingsWidget->pos());
	animation->setEndValue(hide ? point1 : point2);

	QPropertyAnimation *animation2 = new QPropertyAnimation(slide, "geometry");
	animation2->setDuration(1000);
	animation2->setEasingCurve(QEasingCurve::InOutCubic); //InOutBack
	animation2->setStartValue(slide->geometry());
	animation2->setEndValue(hide ? rect1 : rect2);


	animation2->start();
	animation->start();

	connect(animation,SIGNAL(finished()),SLOT(endAnimation()));
}

void MainWindow::endAnimation()
{
	ui->btnShowPanel->setVisible(!_expanded);
	update();
}

void MainWindow::onWindowStyleChanged(QAction* action)
{
	QString style = action->text();

	qApp->setStyle(style);
	QList<QAction*> list = ui->menuWindow_style->actions();
	int num = 0;
	foreach(QAction* act, list){
		act->setChecked(false);
		if(act == action) _provider->settings()->windowStyle = num;
		num++;
	}
	action->setChecked(true);
}

void MainWindow::onTableStyleChanged(QAction* action)
{
	ui->comboTab->clearFields();
	ui->listTab->clearFields();
	ui->actionStyle_1->setChecked(false);
	ui->actionStyle_2->setChecked(false);
	ui->actionStyle_3->setChecked(false);
	if(action == ui->actionStyle_1){
		ui->tabWidget->setCurrentIndex(0);
		_provider->settings()->dataViewStyle = 0;
	}
	else if(action == ui->actionStyle_2){
		ui->tabWidget->setCurrentIndex(1);
		_provider->settings()->dataViewStyle = 1;
	}
	else{
		ui->tabWidget->setCurrentIndex(2);
		_provider->settings()->dataViewStyle = 2;
	}
	action->setChecked(true);
}

void MainWindow::closeEvent(QCloseEvent *event)
{
	QSettings settings("settings.ini",QSettings::IniFormat);
	 settings.setValue("geometry", saveGeometry());
	 settings.setValue("windowState", saveState());
	 settings.setValue("expanded",_expanded);
	 settings.setValue("showDlgAtStartup",_provider->settings()->showDlgAtStartup);
	 settings.setValue("showPass",_provider->settings()->showPass);
	 settings.setValue("userType",_provider->settings()->userType);
	 settings.setValue("database",_provider->settings()->database);
	 settings.setValue("windowStyle",_provider->settings()->windowStyle);
	 settings.setValue("dataViewStyle",_provider->settings()->dataViewStyle);

	 QMainWindow::closeEvent(event);
}

void MainWindow::readSettings()
{
	QFile res(":/font/rsc/century.ttf");
	if(res.open(QIODevice::ReadOnly)){
		QFontDatabase::addApplicationFontFromData(res.readAll());

		QFont newFont = QFont("Century",-1,50);
		newFont.setFixedPitch(false);
		newFont.setStretch(100);
		newFont.setPixelSize(12);
		QApplication::setFont(newFont);
	}


	QFile file("settings.ini");
	if(!file.exists()) return;
	if(!_provider) return;

	QSettings settings("settings.ini",QSettings::IniFormat);
	restoreGeometry(settings.value("geometry").toByteArray());
	restoreState(settings.value("windowState").toByteArray());
	_provider->settings()->expanded = settings.value("expanded").toBool();
	_provider->settings()->showDlgAtStartup = settings.value("showDlgAtStartup").toBool();
	_provider->settings()->showPass = settings.value("showPass").toBool();
	_provider->settings()->userType = (CipherType::Enum) (settings.value("userType").toInt());
	_provider->settings()->database = settings.value("database").toString();
	_provider->settings()->windowStyle = settings.value("windowStyle").toInt();
	_provider->settings()->dataViewStyle = settings.value("dataViewStyle").toInt();

}

void MainWindow::onHelp()
{
	QWebView* web = new QWebView();
	web->show();
	web->page()->settings()->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls,true);
	web->page()->settings()->setAttribute(QWebSettings::LocalContentCanAccessFileUrls,true);
	web->page()->settings()->setAttribute(QWebSettings::LocalStorageEnabled,true);
	web->page()->settings()->setAttribute(QWebSettings::AutoLoadImages,true);
	web->load(QUrl("file:///" + QCoreApplication::applicationDirPath() + "/help/memorizerHelp.html"));
}

void MainWindow::onMakeBackup()
{
	QString filename = _provider->getDatabase()->getCurrentFile();

	QFile file(filename);
	if(!file.exists()){
		ui->statusBar->showMessage(QString(tr("Can't open database (%1)")).arg(filename),3000);
		return;
	}

	QDir dir;
	dir.mkdir("./backup");

	QString backupFile = QString("./backup/backup_%1_%2.mdb")
			.arg(QDate::currentDate().toString("dd-MM-yyyy"))
			.arg(QTime::currentTime().toString("hh-mm-ss"));

	QFileDialog dlg;
	QString saveFile = dlg.getSaveFileName(this,tr("backup database"),backupFile,tr("All Files (*.*)"));
	if(!saveFile.isEmpty()){
		if( !file.copy(saveFile) ){
			ui->statusBar->showMessage(QString(tr("Can't copy database (%1)")).arg(filename),3000);
			return;
		}
		file.close();
	}
}
